package cs421;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class Url {
	
	public Url(String s, Url root) throws IOException {
		parseUrl(s, root);
	}

	public Url(String s) throws IOException {
		parseUrl(s, null);
	}

	public boolean isRelative() {
		return relative;
	}
	
	public void setHost(String host) {
		this.host = host;
		relative = (host == null);
	}

	public void setPath(String path) {
		this.path = path; 
	}
	
	public String getHost() {
		return host;
	}

	public int getPort() {
		return port;
	}

	public String getPath() {
		return path;
	}

	public String getFile() {
		return file;
	}
	
	public boolean equals(Object o) {
		if(o instanceof Url) {
			Url u = (Url) o;
			return this.toString().equals(u.toString());
		}

		return false;
	}
	
	public int hashCode() {
		return this.toString().hashCode();
	}
	
	public String toString() {
		return (isRelative() ? "" : host + ":" + port ) + path + file;
	}
	
	private String host;
	private String path;
	private String 	file;
	private int port;
	private boolean relative;
	

	private void parseUrl(String s, Url root) throws IOException {

		Matcher m;

		if((m = ABSOLUTE_URL_PATTERN.matcher(s)).matches()) {
			// absolute path
			System.out.println("mathed 1");
			host = m.group(1);
			port = m.group(2) != null ? Integer.valueOf(m.group(2)) : 80;
			path = m.group(3);
			file = m.group(4);
			
			if(file.isEmpty())
				file = "index.html";
			
		}   
		else if((m = RELATIVE_URL_PATTERN.matcher(s)).matches()) {
			// relative path
			//TODO: if root==null ...
			System.out.println("mathed 2");
			host = root.getHost();
			port = root.getPort();
			path = m.group(1); 			// NO '/' at the beginning
			if(path.startsWith("/"))
				path = path.substring(1);
			path = root.getPath() + path;
			file = m.group(2);
			
			if(file.isEmpty())
				file = "index.html";
			
		} else if((m = HOST_NAME_PATTERN.matcher(s)).matches()) {
			// a host name
			System.out.println("mathed 3");
			host = m.group(1);
			port = m.group(2) != null ? Integer.valueOf(m.group(2)) : 80;
			path = "/";
			file = "index.html";
		} else	{ 
			// a file name
			System.out.println("mathed 4");
			host = root.getHost();
			port = root.getPort();
			path = root.getPath();
			file = s;
		}
		
	}

	
	public static void main(String[] args) throws IOException {
		String[] ss = new String[] {
				"http://www.cis.upenn.edu/~matuszek/General/RegexTester/regex-tester.html",
				"www.cis.upenn.edu/~matuszek/General/RegexTester/regex-tester.html",
				"/~matuszek/General/RegexTester/regex-tester.html",
				"General/RegexTester/regex-tester.html",
				"/regex-tester.html",
				"regex-tester.html",
				"www.bbc.co.uk",
				"index.jsp"
			};
		Url r = new Url("http://www.cis.upenn.edu/");
		for(String s : ss)
			System.out.println(new Url(s, r));

	}
	
	private static final Pattern ABSOLUTE_URL_PATTERN = Pattern.compile(
			"^(?:http://)?([\\w-]+(?:\\.[\\w-]+)+)(?::(\\d+))?(/(?:[^/.]+/)*)(.*)$", Pattern.CASE_INSENSITIVE);
	private static final Pattern RELATIVE_URL_PATTERN = Pattern.compile(
			"^(/?(?:[^/.]*/)+)(.*)$", Pattern.CASE_INSENSITIVE);
	private static final Pattern HOST_NAME_PATTERN = Pattern.compile(
			"^(?:http://)?((?:(?:[^/\\.]+\\.)+(?:com|edu|gov|int|mil|net|org|biz|info|aero|[a-z][a-z])(?:\\.[a-z][a-z])?)|(?:\\.[a-z][a-z]))(?::(\\d+))?", Pattern.CASE_INSENSITIVE);
}
